﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Syndication;
using System.Xml;
using PBDesk.com.Extension.UmbHelper;
using System.Xml.Linq;
using PBDesk.Utilities;
using System.Web;
using System.Reflection;
using PBDesk.com.Extension.FeedsAggregator.Entities;

namespace PBDesk.com.Extension.FeedsAggregator
{
    public class FeedHelper
    {
        public const int DEFAULT_FEED_ITEM_COUNT = 50;
        public static string Feed_Categories_Config_File = MyUmb.MyConfigsLoc + "FeedCategories.config";

        #region PBDesk RSS Feeds
       
        public static SyndicationFeed GetPBDeskComRss(int itemCount = DEFAULT_FEED_ITEM_COUNT)
        {
            string fileName = MyUmb.CacheFilesLoc + "PBDeskRss.xml";
            SyndicationFeed cachedFeed = GetSyndicationFeedFromUrl(fileName);
            if (cachedFeed == null)
            {
                return GetPBDeskComFreshRss(itemCount);
            }
            return cachedFeed;
        }

       public static SyndicationFeed GetPBDeskComFreshRss(int itemCount = DEFAULT_FEED_ITEM_COUNT)
        {
            MyLog.Write<FeedHelper>("GetPBDeskComFreshRss()", "Method Call Start");
            SyndicationFeed feed = new SyndicationFeed();
            feed.Title = new TextSyndicationContent("www.PBDesk.com");
            feed.Description = new TextSyndicationContent("Updates from www.PBDesk.com - Learning endeavor for ever..... From the desk of Pinal Bhatt, including updates for || LMS || & Blogs");
            feed.Links.Add(new SyndicationLink(new Uri("http://www.PBDesk.com")));
            feed.Links.Add(new SyndicationLink(new Uri("http://lms.PBDesk.com")));
            feed.Links.Add(new SyndicationLink(new Uri("http://blog.PBDesk.com")));
            feed.Links.Add(new SyndicationLink(new Uri("http://www.Twitter.com/PBDesk")));
            feed.ImageUrl = new Uri("http://cdn.PBDesk.com/images/imgs/PBDeskLogo02.png");
            MyLog.Write<FeedHelper>("Feed Object Header Ready");
            feed.Items = GetPBDeskComFeedItems(itemCount);
            return feed;
        }

       internal static IEnumerable<SyndicationItem> GetPBDeskComFeedItems(int itemCount)
        {
            SyndicationFeed feed = new SyndicationFeed();
            MyLog.Write<FeedHelper>("GetPBDeskComFeedItems(): Method call Start");
            IEnumerable<SyndicationItem> blogFeed = GetPBDeskBlogFeedsItems(itemCount);
            MyLog.Write<FeedHelper>("Done call to GetPBDeskBlogFeedsItems");
            IEnumerable<SyndicationItem> twitterFeed = GetTwitterFeedItems("PBDesk", itemCount);
            MyLog.Write<FeedHelper>("Done call to GetTwitterFeedItems");
            IEnumerable<SyndicationItem> lmsFeeds = GetLMSFeedItems(itemCount);
            MyLog.Write<FeedHelper>("done call to GetLMSFeedItems");
            if (blogFeed != null)
                feed.Items = feed.Items.Union(blogFeed);
            if(twitterFeed != null)
                feed.Items = feed.Items.Union(twitterFeed);
            if (lmsFeeds != null)
                feed.Items = feed.Items.Union(lmsFeeds);            
            feed.Items = feed.Items.OrderByDescending(dt => dt.PublishDate).Take(itemCount);
            return feed.Items;
        }

       private static IEnumerable<SyndicationItem> GetLMSFeedItems(int itemCount)
        {
            string feedUrl = "http://lms.pbdesk.com/rss/file.php/55/b0c04bbf7d525f20454f5fdec5963cf8/mod_forum/2/rss.xml";
            SyndicationFeed feed = GetSyndicationFeedFromUrl(feedUrl, itemCount);
            if (feed != null && feed.Items != null)
            {
                return feed.Items;
            }
            else
            {
                return null;
            }
        }

        private static IEnumerable<SyndicationItem> GetPBDeskBlogFeedsItems(int itemCount)
        {
            string feedUrl = string.Format("http://blog.pbdesk.com/feeds/posts/default?alt=rss&max-results={0}", itemCount);
            SyndicationFeed feed = GetSyndicationFeedFromUrl(feedUrl, itemCount);
            foreach (SyndicationItem item in feed.Items)
            {
                item.Authors.Clear();
                item.Authors.Add(SyndicationHelper.GetSyndicationPerson());

                StringBuilder labelText = new StringBuilder("Blog Post filed under Labels: ");
                foreach (SyndicationCategory category in item.Categories)
                {
                    labelText.Append(category.Name + ", ");
                }
                labelText = labelText.Remove(labelText.Length - 2, 2);
                item.Summary = new TextSyndicationContent(labelText.ToString(), TextSyndicationContentKind.Html);
                item.Categories.Add(new SyndicationCategory("Blog Post"));
                item.Title = new TextSyndicationContent("Blog Post: " + item.Title.Text);

            }
            return feed.Items;
        }

        #endregion

        #region Helper Methods
        
        internal static SyndicationFeed GetSyndicationFeedFromUrl(string url, int itemCount = DEFAULT_FEED_ITEM_COUNT)
        {

            SyndicationFeed feed = null;
            try
            {
                using (XmlReader reader = CustomXmlReader.Create(url))
                {
                    feed = SyndicationFeed.Load(reader);
                    feed.Items = feed.Items.OrderByDescending(dt => dt.PublishDate).Take(itemCount);
                    reader.Close();                  
                }
            }
            catch (Exception ex)
            {
                MyLog.WriteErr<FeedHelper>(string.Format("Error at GetSyndicationFeedFromUrl for url {0}", url), ex);
            }
            return feed;
        }

        internal static IEnumerable<SyndicationItem> GetTwitterFeedItems(string twitterHandle, int itemCount = DEFAULT_FEED_ITEM_COUNT)
        {
            SyndicationFeed feed = GetTwitterFeeds(twitterHandle, itemCount * 2);
            if (feed != null && feed.Items != null && feed.Items.Count() > 0)
            {
                SyndicationFeed feed1 = new SyndicationFeed(feed.Items.Where(p => p.Title.Text.ToLower().Contains("#pbdesk")));
                foreach (SyndicationItem item in feed1.Items)
                {
                    item.Authors.Clear();
                    item.Authors.Add(SyndicationHelper.GetSyndicationPerson());
                    item.Categories.Add(new SyndicationCategory("Twitter"));
                    item.Title = new TextSyndicationContent(item.Title.Text.Replace(twitterHandle.ToLower() + ":", "Twitter:"));                    
                }

                return feed1.Items;
            }
            return null;
        }
        internal static SyndicationFeed GetTwitterFeeds(string twitterHandle, int itemCount = DEFAULT_FEED_ITEM_COUNT)
        {
            SyndicationFeed feed = null;
            try
            {
                string feedUrl = string.Format("http://twitter.com/statuses/user_timeline/{0}.rss?count={1}", twitterHandle, itemCount);

                feed = GetSyndicationFeedFromUrl(feedUrl, itemCount);
             
            }
            catch (Exception ex)
            {
                MyLog.WriteErr<FeedHelper>(string.Format("Error at GetTwitterFeeds for twitterHandle {0}", twitterHandle), ex);
            }
            return feed;
            
        }

        #endregion

        #region TWC9

        internal static C9Item GetTWC9()
        {
            C9Item c9Item = null;
            try
            {
                string fileName = MyUmb.CacheFilesLoc + "TWC9.xml";
                SyndicationFeed feed = GetSyndicationFeedFromUrl(fileName, 1);
                if(feed == null)
                     feed = GetSyndicationFeedFromUrl("http://channel9.msdn.com/Shows/This+Week+On+Channel+9/RSS", 1);
                if (feed != null && feed.Items.Count() == 1)
                {
                    SyndicationItem feedItem = feed.Items.FirstOrDefault();
                    c9Item = GetC9ItemFromFeedItem(feedItem);                    
                }

            }
            catch (Exception ex)
            {
                MyLog.WriteErr<AdminTasks>("Error in FeedHelper::GetTWC9()", ex);
            }
            return c9Item;
               
        }

        internal static List<C9Item> GetTWC9Items(int itemCount = 50)
        {
            List<C9Item> returnList = new List<C9Item>();
            try
            {
                string fileName = HttpContext.Current.Request.PhysicalApplicationPath + "App_Data\\MyUmb\\TWC9.xml";
                SyndicationFeed feed = GetSyndicationFeedFromUrl(fileName, itemCount);
                if (feed == null)
                    feed = GetSyndicationFeedFromUrl("http://channel9.msdn.com/Shows/This+Week+On+Channel+9/RSS", itemCount);
                if (feed != null && feed.Items.Count() >= 2)
                {
                   
                    foreach (SyndicationItem item in feed.Items)
                    {
                        C9Item c9Item = GetC9ItemFromFeedItem(item);
                        if (c9Item != null)
                            returnList.Add(c9Item); 
                    }
                }

            }
            catch(Exception ex)
            {
                MyLog.WriteErr<AdminTasks>("Error in FeedHelper::GetTWC9Items()", ex);
            }            
            return returnList;
        }

        internal static C9Item GetC9ItemFromFeedItem(SyndicationItem feedItem)
        {
            C9Item c9Item = new C9Item();
            c9Item.Title = feedItem.Title.Text;
            c9Item.Description = feedItem.Summary.Text;
            c9Item.PageLink = feedItem.Links[0].Uri.AbsoluteUri;
            c9Item.PubDate = feedItem.PublishDate.DateTime;
            foreach (SyndicationElementExtension x in feedItem.ElementExtensions)
            {
                if (x.OuterNamespace == "http://search.yahoo.com/mrss/")
                {
                    if (x.OuterName == "thumbnail")
                    {
                        XElement thumbnailElement = x.GetObject<XElement>();
                        var thumbnails = from x1 in thumbnailElement.DescendantsAndSelf()
                                 select new Thumbnail
                                 {
                                     Url = x1.Attribute("url").Value,
                                     Height = x1.Attribute("height").Value.As<int>(),
                                     Width = x1.Attribute("width").Value.As<int>()
                                 };
                        c9Item.Thumbnails.Add(thumbnails.FirstOrDefault());
                        
                    }
                    else if (x.OuterName == "group" )
                    {
                        var mediaElement = x.GetObject<XElement>();                       
                        var allMedia = from x2 in mediaElement.Elements()
                                       select new Media
                                       {
                                           Url = x2.Attribute("url").Value,
                                           Duration = x2.Attribute("duration").Value.As<int>(),
                                           FileSize = x2.Attribute("fileSize").Value.As<long>(),
                                           MediaFormat = GetMediaType(x2.Attribute("type").Value, x2.Attribute("url").Value)
                                       };
                        c9Item.Media.AddRange(allMedia);

                    }
                }
            }
            return c9Item;
        }

        private static MediaType GetMediaType(string mediaTypeStr, string url)
        {
            MediaType mediaFormat = MediaType.Unknown;
            if (mediaTypeStr.ToLower() == "video/mp4")
            {
                if (url.Contains("high")) mediaFormat = MediaType.VideoMP4High;
                else if (url.Contains("med") || url.Contains("mid")) mediaFormat = MediaType.VideoMP4Med;
                else if (url.Contains("low")) mediaFormat = MediaType.VideoMP4Low;
            }
            else if (mediaTypeStr.ToLower() == "audio/mp3") mediaFormat = MediaType.AudioMP3;
            else if (mediaTypeStr.ToLower() == "video/webm") mediaFormat = MediaType.VideoWebm;
            else if (mediaTypeStr.ToLower().Contains("wmv")) mediaFormat = MediaType.WMV;
            else if (mediaTypeStr.ToLower().Contains("wma")) mediaFormat = MediaType.WMA;
                
            return mediaFormat;
        }

        public static string GetMP4Media(C9Item twc9Item)
        {
            string vfileUrl = null;
            if (twc9Item != null && twc9Item.Media != null && twc9Item.Media.Count > 0)
            {
                var files = from Media m in twc9Item.Media
                            where m.MediaFormat == MediaType.VideoMP4 ||
                                  m.MediaFormat == MediaType.VideoMP4High ||
                                  m.MediaFormat == MediaType.VideoMP4Med ||
                                  m.MediaFormat == MediaType.VideoMP4Low
                            select m.Url;
                vfileUrl = files.FirstOrDefault();
            }
            return vfileUrl;
        }
        #endregion

        #region Feed Category Methods
        
        public static FeedCategory GetFeedCategory(string categoryName)
        {
            FeedCategory retVal = null;
            if (categoryName.IsNotNullAndNotEmpty())
            {
                categoryName = categoryName.ToLower();

                try
                {
                    XDocument xDoc = FileOpHelper.GetXMLFile(Feed_Categories_Config_File);
                    if (xDoc != null)
                    {
                        var list = from category in xDoc.Descendants("feedCategory")
                                   where category.Attribute("name").Value == categoryName
                                   select new FeedCategory
                                   {
                                       Name = category.Attribute("name").Value,
                                       Desc = category.Attribute("desc").Value,
                                       Title = category.Attribute("title").Value,
                                       Link = category.Attribute("link").Value,
                                       CacheFileName = category.Attribute("cacheFile").Value,
                                       FeedSourceUrls = (from urlItem in category.Descendants("url")
                                                         select urlItem.Attribute("value").Value).ToList<string>()
                                   };

                        if (list != null && list.FirstOrDefault() != null)
                            retVal = list.FirstOrDefault();
                    }
                    else
                    {
                        throw new Exception("XDocument xDoc is null for categoryName=" + categoryName);
                    }
                }
                catch (Exception ex)
                {
                    MyLog.WriteErr<FeedHelper>("Error in GetFeedCategory(category)", ex);
                }
            }


            return retVal;
        }

        public static List<FeedCategory> GetFeedCategories()
        {
            try
            {
                XDocument xDoc = FileOpHelper.GetXMLFile(Feed_Categories_Config_File);
                if (xDoc != null)
                {
                    var list = (from category in xDoc.Descendants("feedCategory")
                                select new FeedCategory
                                {
                                    Name = category.Attribute("name").Value.ToLower(),
                                    Desc = category.Attribute("desc").Value,
                                    Title = category.Attribute("title").Value,
                                    Link = category.Attribute("link").Value,
                                    CacheFileName = category.Attribute("cacheFile").Value,
                                    BatchJob = category.Attribute("batch").Value.ToUpper(),
                                    FeedSourceUrls = (from urlItem in category.Descendants("url")
                                                      select urlItem.Attribute("value").Value).ToList<string>()
                                }).ToList<FeedCategory>();

                    if (list != null)
                        return list;

                }
                else
                {
                    throw new Exception("XDocument xDoc is null for categoryName=");
                }
            }
            catch (Exception ex)
            {
                MyLog.WriteErr<FeedCategory>("Error in GetFeedCategories()", ex);
            }



            return null;
        }

        #endregion

        public static SyndicationFeed GetTechNewsFeeds(string category)
        {
            return  GetTechNewsFeeds(GetFeedCategory(category));

        }

        public static SyndicationFeed GetTechNewsFeeds(FeedCategory feedCategory)
        {
            SyndicationFeed feed = new SyndicationFeed();
            if (feedCategory != null)
            {
                feed = GetSyndicationFeedFromUrl(MyUmb.CacheFilesLoc + feedCategory.CacheFileName);
            }
            return feed;

        }


    }
}
